﻿#if !UNITY_WSA || UNITY_EDITOR
using System.Security.Cryptography;
#else
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
#endif
using System;
using XLua;

namespace ClientStructure
{
	public class LuaLoader
	{

		private LuaEnv.CustomLoader userLoader;
#if !UNITY_WSA || UNITY_EDITOR
		RSACryptoServiceProvider rsa;
		SHA1 sha;
#else
        AsymmetricKeyAlgorithmProvider rsa;
        CryptographicKey key;
#endif

		public LuaLoader(string publicKey, LuaEnv.CustomLoader loader)
		{
#if !UNITY_WSA || UNITY_EDITOR
			rsa = new RSACryptoServiceProvider();
			rsa.ImportCspBlob(Convert.FromBase64String(publicKey));
			sha = new SHA1CryptoServiceProvider();
#else
            rsa = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaSignPkcs1Sha1);
            key = rsa.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(publicKey), CryptographicPublicKeyBlobType.Capi1PublicKey);
#endif
			userLoader = loader;
		}
		
		byte[] load_and_verify(ref string filepath)
		{
			byte[] data = userLoader(ref filepath);
			if (data == null)
			{
				return null;
			}
			if (data.Length < 128)
			{
				throw new InvalidProgramException(filepath + " length less than 128!");
			}

			byte[] sig = new byte[128];
			byte[] filecontent = new byte[data.Length - 128];
			Array.Copy(data, sig, 128);
			Array.Copy(data, 128, filecontent, 0, filecontent.Length);

#if !UNITY_WSA || UNITY_EDITOR
			if (!rsa.VerifyData(filecontent, sha, sig))
			{
				throw new InvalidProgramException(filepath + " has invalid signature!");
			}
#else
            if (!CryptographicEngine.VerifySignature(key, CryptographicBuffer.CreateFromByteArray(filecontent), CryptographicBuffer.CreateFromByteArray(sig)))
            {
                throw new InvalidProgramException(filepath + " has invalid signature!");
            }
#endif
			return filecontent;
		}

		public static implicit operator LuaEnv.CustomLoader(LuaLoader luaLoader)
		{
			return luaLoader.load_and_verify;
		}
	}
}